// Copyright 2007 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.enterprise.onebox.apps;

import com.google.enterprise.onebox.apps.SimpleOneBoxResults.ModuleResult;

import com.google.gdata.client.Query;
import com.google.gdata.client.docs.DocsService;
import com.google.gdata.data.docs.DocumentListEntry;
import com.google.gdata.data.docs.DocumentListFeed;
import com.google.gdata.data.Category;
import com.google.gdata.util.ServiceException;

import java.util.*;
import java.util.logging.*;
import java.net.*;
import java.io.*;

/**
 * This class plays the SimpleOneBoxProvider role in the case of Google Docs,
 * finding documents, spreadsheets, as well as presentations that match a full
 * text query.
 * 
 * @author amsmith@google.com (Adam Smith)
 *
 */
public class DocsProvider implements SimpleOneBoxProvider {
  
  private static final Logger LOGGER =
    Logger.getLogger(DocsProvider.class.getName());

  private static final String FEED_URL_STRING =
    "https://docs.google.com/feeds/documents/private/full";
  private static final String SERVICE_NAME = "Google-AppsOneBox-0";
  private static final int MAX_RESULTS = 5;
  private static final Map<String,String> IMAGE_SOURCES;
  
  
  static {
    IMAGE_SOURCES = new HashMap<String,String>();
    IMAGE_SOURCES.put(
        "http://schemas.google.com/docs/2007#document", 
        "https://docs.google.com/a/google.com/images/doclist/icon_2_doc.gif");
    IMAGE_SOURCES.put(
        "http://schemas.google.com/docs/2007#spreadsheet",
        "https://docs.google.com/a/google.com/images/doclist/icon_2_spread.gif");
    IMAGE_SOURCES.put(
        "http://schemas.google.com/docs/2007#presentation",
        "https://docs.google.com/a/google.com/images/doclist/icon_2_pres.gif");
  }
  
  /**
   * This method defers to the larger method below after injecting a vanilla
   * DocsService object.
   */
  public SimpleOneBoxResults getResults(String queryString,
      String userName, String password) {
    DocsService service = new DocsService(SERVICE_NAME);
    return getResults(queryString, userName, password, service);
  }
  
  /**
   * Performs a full text query of Google Docs as the given user, returning a
   * result containing the obvious data as well as an 'icon' field that can be
   * used to show icon images next to search results (illustrating the document
   * type).
   */
  public SimpleOneBoxResults getResults(String queryString,
      String userName, String password, DocsService service) {
    
    try {
      service.setUserCredentials(userName, password);
    } catch (ServiceException se) {
      LOGGER.info(se.toString());
      return null;
    }
    
    URL feedUrl = null;
    try {
      feedUrl = new URL(FEED_URL_STRING);
    } catch(MalformedURLException murle) {
      LOGGER.severe(murle.toString());
      return null;
    }
    
    Query query = new Query(feedUrl);
    query.setFullTextQuery(queryString);
    query.setMaxResults(MAX_RESULTS);
    DocumentListFeed feed = null;
    try {
      feed = service.query(query, DocumentListFeed.class);
    } catch (ServiceException se) {
      LOGGER.severe(se.toString());
      return null;
    } catch (IOException ioe) {
      LOGGER.severe(ioe.toString());
      return null;
    }
 
    SimpleOneBoxResults results = new SimpleOneBoxResults();
    results.setProviderName("Google Docs");
    results.setTotalResults(feed.getTotalResults());
    if (feed.getLink("alternate", null) != null) {
      results.setLink(feed.getLink("alternate", null).getHref());
    }
    results.setQuery(queryString);
    for (DocumentListEntry doc : feed.getEntries()) {
      ModuleResult result = new ModuleResult();
      result.setUrl(doc.getHtmlLink().getHref());
      result.setTitle(doc.getTitle().getPlainText());
      result.putField("icon", getIcon(doc));
      results.getResults().add(result);
    }
    
    return results;
  }
  
  /**
   * Determines the type of document passed in and looks up the associated icon
   * image URL for that type.  Returns null if no match was found.
   */
  private static String getIcon(DocumentListEntry doc) {
    String source = null;
    
    // Normally there is only one category, but if there are many we will end
    // using keeping the last one.
    Set<Category> categories = doc.getCategories();
    for (Iterator<Category> i = categories.iterator(); i.hasNext(); ) {
      Category category = i.next();
      source = IMAGE_SOURCES.get(category.getTerm());
    }
    return source;
  }
}
